﻿using System;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;
using HYElectricKernel;

namespace Model
{
	public class CableTrayAlignment : HYCmdEntry
	{
		public CableTrayAlignment(ExternalCommandData commandData) : base(commandData)
		{
		}

		public void Excute()
		{
			DlgCableTrayAlignment dlgCableTrayAlignment = new DlgCableTrayAlignment();
			dlgCableTrayAlignment.Show(WindowHelper.HWndRevit);
			WindowHelper.SendMessageToWndRevit();
			Transaction transaction = new Transaction(this.m_doc, "Alignment");
			for (;;)
			{
				try
				{
					Reference reference = this.m_sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new RevitFilter.SelectionCableTrayFilter(), "请选择基准桥架");
					Reference reference2 = this.m_sel.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new RevitFilter.SelectionCableTrayFilter(), "请选择对齐桥架");
					CableTray cableTray = this.m_doc.GetElement(reference) as CableTray;
					CableTray cableTray2 = this.m_doc.GetElement(reference2) as CableTray;
					HYCableTray<CableTray> hycableTray = new HYCableTray<CableTray>(cableTray);
					HYCableTray<CableTray> hycableTray2 = new HYCableTray<CableTray>(cableTray2);
					if (cableTray.Id == cableTray2.Id)
					{
						continue;
					}
					if (!hycableTray.IsParallel(cableTray2))
					{
						TaskDialog.Show("盈建科提示", "选中的两条桥架必须平行。");
						continue;
					}
					XYZ xyz = -hycableTray.CustomConnectorStart.Connector.CoordinateSystem.BasisY;
					XYZ xyz2 = -hycableTray2.CustomConnectorStart.Connector.CoordinateSystem.BasisY;
					if (!xyz.IsAlmostEqualTo(xyz2))
					{
						TaskDialog.Show("盈建科提示", "选中的两条桥架的开槽方向必须一致。");
						continue;
					}
					double num = cableTray.Width / 2.0;
					double num2 = cableTray2.Width / 2.0;
					double num3 = cableTray.Height / 2.0;
					double num4 = cableTray2.Height / 2.0;
					transaction.Start();
					if (Geometry.IsEqual(hycableTray.StartXYZ.Z, hycableTray.EndXYZ.Z) && Geometry.IsEqual(hycableTray2.StartXYZ.Z, hycableTray2.EndXYZ.Z) && xyz.IsAlmostEqualTo(xyz2) && xyz.IsAlmostEqualTo(XYZ.BasisZ))
					{
						XYZ endPointByHorizontalCableTray;
						if (hycableTray.IsYAxis() && hycableTray2.IsYAxis())
						{
							endPointByHorizontalCableTray = this.GetEndPointByHorizontalCableTray(hycableTray, true);
						}
						else
						{
							endPointByHorizontalCableTray = this.GetEndPointByHorizontalCableTray(hycableTray, false);
						}
						XYZ basisZ = hycableTray.GetCloseConnector(endPointByHorizontalCableTray).CoordinateSystem.BasisZ;
						if (dlgCableTrayAlignment.chkHorizontalAlignment.Checked)
						{
							XYZ xyz4;
							XYZ xyz5;
							if (dlgCableTrayAlignment.rdoLeftAlignment.Checked)
							{
								XYZ xyz3 = Geometry.RotateTo(basisZ, Math.PI*.5, XYZ.BasisZ);
								xyz4 = endPointByHorizontalCableTray + xyz3 * num;
								xyz5 = hycableTray2.StartXYZ + xyz3 * num2;
							}
							else if (dlgCableTrayAlignment.rdoRightAlign.Checked)
							{
								XYZ xyz6 = Geometry.RotateTo(basisZ, -Math.PI*.5, XYZ.BasisZ);
								xyz4 = endPointByHorizontalCableTray + xyz6 * num;
								xyz5 = hycableTray2.StartXYZ + xyz6 * num2;
							}
							else
							{
								xyz4 = endPointByHorizontalCableTray;
								xyz5 = hycableTray2.StartXYZ;
							}
							Line line = Line.CreateUnbound(xyz4, basisZ);
							line.MakeUnbound();
							XYZ xyzpoint = line.Project(xyz5).XYZPoint;
							XYZ xyz7 = new XYZ(xyzpoint.X, xyzpoint.Y, xyz5.Z) - xyz5;
							hycableTray2.CableTray.Location.Move(xyz7);
							this.m_doc.Regenerate();
						}
						if (dlgCableTrayAlignment.chkVerticalBottomAlignment.Checked)
						{
							this.SetHorizontalCableTrayBottomAlignment(cableTray, cableTray2);
							this.m_doc.Regenerate();
						}
					}
					else if (!Geometry.IsEqual(hycableTray.StartXYZ.Z, hycableTray.EndXYZ.Z) && hycableTray.CustomConnectorStart.Connector.CoordinateSystem.BasisX.Z == 0.0)
					{
						XYZ sameLevelProjPt = this.GetSameLevelProjPt(hycableTray, hycableTray2);
						XYZ basisX = hycableTray.CustomConnectorStart.Connector.CoordinateSystem.BasisX;
						XYZ xyz8 = hycableTray.StartXYZ + basisX * num;
						XYZ xyz9 = (new XYZ(xyz8.X, xyz8.Y, hycableTray.StartXYZ.Z) - hycableTray.StartXYZ).Normalize();
						if (dlgCableTrayAlignment.chkHorizontalAlignment.Checked)
						{
							XYZ xyz10 = Geometry.RotateTo(xyz9, Math.PI*.5, XYZ.BasisZ);
							Line line2 = Line.CreateUnbound(hycableTray.StartXYZ, xyz10);
							line2.MakeUnbound();
							XYZ xyz11 = line2.Project(sameLevelProjPt).XYZPoint - sameLevelProjPt;
							hycableTray2.CableTray.Location.Move(xyz11);
							this.m_doc.Regenerate();
							if (!dlgCableTrayAlignment.rdoAlign.Checked)
							{
								XYZ axis;
								if (hycableTray2.StartXYZ.Z > hycableTray2.EndXYZ.Z)
								{
									axis = (hycableTray2.EndXYZ - hycableTray2.StartXYZ).Normalize();
								}
								else
								{
									axis = (hycableTray2.StartXYZ - hycableTray2.EndXYZ).Normalize();
								}
								XYZ xyz12 = null;
								if (dlgCableTrayAlignment.rdoLeftAlignment.Checked)
								{
									xyz12 = Geometry.RotateTo(xyz, Math.PI*.5, axis);
								}
								else if (dlgCableTrayAlignment.rdoRightAlign.Checked)
								{
									xyz12 = Geometry.RotateTo(xyz, -Math.PI*.5, axis);
								}
								XYZ xyz13 = hycableTray.StartXYZ + xyz12 * num;
								xyz10 = (new XYZ(xyz13.X, xyz13.Y, hycableTray.StartXYZ.Z) - hycableTray.StartXYZ).Normalize();
								double d = xyz10.AngleTo(xyz12);
								double num5 = num / Math.Cos(d);
								double num6 = num2 / Math.Cos(d);
								double num7 = num5 - num6;
								xyz11 = hycableTray2.StartXYZ + xyz10 * num7 - hycableTray2.StartXYZ;
								hycableTray2.CableTray.Location.Move(xyz11);
								this.m_doc.Regenerate();
							}
						}
						if (dlgCableTrayAlignment.chkVerticalBottomAlignment.Checked)
						{
							XYZ basisZ2 = hycableTray.CustomConnectorStart.Connector.CoordinateSystem.BasisZ;
							Line line3 = Line.CreateUnbound(hycableTray.StartXYZ, xyz9);
							line3.MakeUnbound();
							Line line4 = Line.CreateUnbound(line3.Project(hycableTray2.StartXYZ).XYZPoint, basisZ2);
							line4.MakeUnbound();
							XYZ xyz14 = line4.Project(hycableTray2.StartXYZ).XYZPoint - hycableTray2.StartXYZ;
							hycableTray2.CableTray.Location.Move(xyz14);
							this.m_doc.Regenerate();
							xyz14 = hycableTray2.StartXYZ - xyz * (num3 - num4) - hycableTray2.StartXYZ;
							hycableTray2.CableTray.Location.Move(xyz14);
							this.m_doc.Regenerate();
						}
					}
					transaction.Commit();
					continue;
				}
				catch (Exception)
				{
                    if ((int)transaction.GetStatus() == 1)
					{
						transaction.RollBack();
					}
					dlgCableTrayAlignment.Close();
				}
				break;
			}
		}

		private XYZ GetSameLevelProjPt(HYCableTray<CableTray> hyct1, HYCableTray<CableTray> hyct2)
		{
			double num = (hyct1.StartXYZ.Z - hyct2.EndXYZ.Z) / (hyct2.StartXYZ.Z - hyct2.EndXYZ.Z);
			double num2 = num * (hyct2.StartXYZ.X - hyct2.EndXYZ.X) + hyct2.EndXYZ.X;
			double num3 = num * (hyct2.StartXYZ.Y - hyct2.EndXYZ.Y) + hyct2.EndXYZ.Y;
			return new XYZ(num2, num3, hyct1.StartXYZ.Z);
		}

		private void SetHorizontalCableTrayBottomAlignment(CableTray baseCableTray, CableTray alignCableTray)
		{
			double num = baseCableTray.Height / 2.0;
			double num2 = alignCableTray.Height / 2.0;
			double num3 = num - num2;
			ElementId elementId = baseCableTray.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsElementId();
			double elevation = (this.m_doc.GetElementById(elementId) as Level).Elevation;
			double num4 = baseCableTray.GetParameter(BuiltInParameter.RBS_OFFSET_PARAM).AsDouble();
			double num5 = elevation + num4;
			elementId = alignCableTray.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsElementId();
			elevation = (this.m_doc.GetElementById(elementId) as Level).Elevation;
			double num6 = num5 - elevation;
			alignCableTray.GetParameter(BuiltInParameter.RBS_OFFSET_PARAM).Set(num6 - num3);
		}

		private XYZ GetEndPointByHorizontalCableTray(HYCableTray<CableTray> hyCableTray, bool isYAxis)
		{
			XYZ startXYZ = hyCableTray.StartXYZ;
			XYZ endXYZ = hyCableTray.EndXYZ;
			XYZ result;
			if (isYAxis)
			{
				if (startXYZ.Y > endXYZ.Y)
				{
					result = startXYZ;
				}
				else
				{
					result = endXYZ;
				}
			}
			else if (startXYZ.X > endXYZ.X)
			{
				result = startXYZ;
			}
			else
			{
				result = endXYZ;
			}
			return result;
		}
	}
}
